"It can be used only by extensions.gnome.org"
#define PLUGIN_MIME_STRING "application/x-gnome-shell-integration::Gnome Shell Integration Dummy Content-Type";
-#define PLUGIN_API_VERSION 4
+#define PLUGIN_API_VERSION 5
typedef struct {
GDBusProxy *proxy;
*(gboolean *) arg_location = NPVARIANT_TO_BOOLEAN (arg);
break;
+
+ case 'o':
+ if (!NPVARIANT_IS_OBJECT (arg))
+ goto out;
+
+ *(NPObject **) arg_location = NPVARIANT_TO_OBJECT (arg);
}
}
return ret;
}
+typedef struct _AsyncClosure AsyncClosure;
+
+struct _AsyncClosure {
+ PluginObject *obj;
+ NPObject *callback;
+ NPObject *errback;
+};
+
+static void
+install_extension_cb (GObject *proxy,
+ GAsyncResult *async_res,
+ gpointer user_data)
+{
+ AsyncClosure *async_closure = (AsyncClosure *) user_data;
+ GError *error = NULL;
+ GVariant *res;
+ NPVariant args[1];
+ NPVariant result = { NPVariantType_Void };
+ NPObject *callback;
+
+ res = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), async_res, &error);
+
+ if (res == NULL)
+ {
+ if (g_dbus_error_is_remote_error (error))
+ g_dbus_error_strip_remote_error (error);
+ STRINGZ_TO_NPVARIANT (error->message, args[0]);
+ callback = async_closure->errback;
+ }
+ else
+ {
+ char *string_result;
+ g_variant_get (res, "(&s)", &string_result);
+ STRINGZ_TO_NPVARIANT (string_result, args[0]);
+ callback = async_closure->callback;
+ }
+
+ funcs.invokeDefault (async_closure->obj->instance,
+ callback, args, 1, &result);
+
+ funcs.releasevariantvalue (&result);
+
+ funcs.releaseobject (async_closure->callback);
+ funcs.releaseobject (async_closure->errback);
+ g_slice_free (AsyncClosure, async_closure);
+}
+
static gboolean
plugin_install_extension (PluginObject *obj,
uint32_t argc,
NPVariant *result)
{
gchar *uuid;
+ NPObject *callback, *errback;
+ AsyncClosure *async_closure;
- if (!parse_args ("u", argc, argv, &uuid))
+ if (!parse_args ("uoo", argc, argv, &uuid, &callback, &errback))
return FALSE;
+ async_closure = g_slice_new (AsyncClosure);
+ async_closure->obj = obj;
+ async_closure->callback = funcs.retainobject (callback);
+ async_closure->errback = funcs.retainobject (errback);
+
g_dbus_proxy_call (obj->proxy,
"InstallRemoteExtension",
g_variant_new ("(s)", uuid),
G_DBUS_CALL_FLAGS_NONE,
-1, /* timeout */
NULL, /* cancellable */
- NULL, /* callback */
- NULL /* user_data */);
+ install_extension_cb,
+ async_closure);
g_free (uuid);
let _httpSession;
-function installExtensionFromUUID(uuid) {
+function installExtensionFromUUID(uuid, invocation) {
let params = { uuid: uuid,
shell_version: Config.PACKAGE_VERSION };
_httpSession.queue_message(message, function(session, message) {
if (message.status_code != Soup.KnownStatusCode.OK) {
ExtensionSystem.logExtensionError(uuid, 'downloading info: ' + message.status_code);
+ invocation.return_dbus_error('org.gnome.Shell.DownloadInfoError', message.status_code.toString());
return;
}
info = JSON.parse(message.response_body.data);
} catch (e) {
ExtensionSystem.logExtensionError(uuid, 'parsing info: ' + e);
+ invocation.return_dbus_error('org.gnome.Shell.ParseInfoError', e.toString());
return;
}
- let dialog = new InstallExtensionDialog(uuid, info);
+ let dialog = new InstallExtensionDialog(uuid, info, invocation);
dialog.open(global.get_current_time());
});
}
return true;
}
-function gotExtensionZipFile(session, message, uuid) {
+function gotExtensionZipFile(session, message, uuid, callback, errback) {
if (message.status_code != Soup.KnownStatusCode.OK) {
- ExtensionSystem.logExtensionError(uuid, 'downloading extension: ' + message.status_code);
+ errback('DownloadExtensionError', message.status_code);
return;
}
if (!dir.query_exists(null))
dir.make_directory_with_parents(null);
} catch (e) {
- ExtensionSystem.logExtensionError(uuid, 'Could not create extension directory');
+ errback('CreateExtensionDirectoryError', e);
return;
}
null);
if (!success) {
- ExtensionSystem.logExtensionError(uuid, 'extract: could not extract');
+ errback('ExtractExtensionError');
return;
}
GLib.spawn_close_pid(pid);
if (status != 0) {
- ExtensionSystem.logExtensionError(uuid, 'extract: could not extract');
- invocation.return_dbus_error('org.gnome.Shell.ExtractExtensionError', '');
+ errback('ExtractExtensionError');
return;
}
let extension = ExtensionUtils.createExtensionObject(uuid, dir, ExtensionUtils.ExtensionType.PER_USER);
ExtensionSystem.loadExtension(extension);
+ callback();
});
}
Name: 'InstallExtensionDialog',
Extends: ModalDialog.ModalDialog,
- _init: function(uuid, info) {
+ _init: function(uuid, info, invocation) {
this.parent({ styleClass: 'extension-dialog' });
this._uuid = uuid;
this._info = info;
+ this._invocation = invocation;
this.setButtons([{ label: _("Cancel"),
action: Lang.bind(this, this._onCancelButtonPressed),
_onCancelButtonPressed: function(button, event) {
this.close(global.get_current_time());
-
- // Even though the extension is already "uninstalled", send through
- // a state-changed signal for any users who want to know if the install
- // went through correctly -- using proper async DBus would block more
- // traditional clients like the plugin
- let meta = { uuid: this._uuid,
- state: ExtensionSystem.ExtensionState.UNINSTALLED,
- error: '' };
-
- _signals.emit('extension-state-changed', meta);
+ this._invocation.return_value(GLib.Variant.new('(s)', ['cancelled']));
},
_onInstallButtonPressed: function(button, event) {
- let state = { uuid: this._uuid,
- state: ExtensionSystem.ExtensionState.DOWNLOADING,
- error: '' };
-
- _signals.emit('extension-state-changed', state);
-
let params = { shell_version: Config.PACKAGE_VERSION };
let url = REPOSITORY_URL_DOWNLOAD.format(this._uuid);
let message = Soup.form_request_new_from_hash('GET', url, params);
- _httpSession.queue_message(message,
- Lang.bind(this, function(session, message) {
- gotExtensionZipFile(session, message, this._uuid);
- }));
+ let invocation = this._invocation;
+ function errback(code, message) {
+ invocation.return_dbus_error('org.gnome.Shell.' + code, message ? message.toString() : '');
+ }
+
+ function callback() {
+ invocation.return_value(GLib.Variant.new('(s)', 'successful'));
+ }
+
+ _httpSession.queue_message(message, Lang.bind(this, function(session, message) {
+ gotExtensionZipFile(session, message, this._uuid, callback, errback);
+ }));
this.close(global.get_current_time());
}